
package com.tianya.utils;

import lombok.extern.slf4j.Slf4j;
import java.util.Base64;

import static com.tianya.utils.FastDFSUploadUtil.uploadFile;

/**
 * 图片工具类，提供图片上传功能。
 */
@Slf4j
public class ImageUtils {

    // 图片大小限制，单位：字节
    private static final int MAX_IMAGE_SIZE = 1024 * 1024;

    /**
     * 上传Base64编码的图片。
     *
     * @param base64Str Base64编码的图片字符串。
     * @param fileExt 图片的文件扩展名。
     * @return 上传后的图片URL。
     * @throws IllegalArgumentException 如果Base64字符串为空或图片大小超过限制。
     */
    public static String uploadImage(String base64Str, String fileExt) {
        if(base64Str == null || base64Str.isEmpty()) {
            throw new IllegalArgumentException("Base64字符串不能为空");
        }
        // 验证fileExt，确保其符合期望的格式，只允许小写字母和点号
        if (!fileExt.matches("[a-z]+\\.[a-z]+")) {
            throw new IllegalArgumentException("不支持的文件扩展名：" + fileExt);
        }

        int imageSize = calculateBase64EncodedImageSize(base64Str);
        if(imageSize > MAX_IMAGE_SIZE){
            throw new IllegalArgumentException("图片大小超过限制");
        }

        // Base64解码
        byte[] decodedBytes = Base64.getDecoder().decode(base64Str);
        String url;
        try {
            url = uploadFile(decodedBytes, fileExt);
        } catch (Exception e) {
            log.error("文件上传失败", e);
            throw new RuntimeException("文件上传失败", e);
        }
        return url;
    }

    /**
     * 计算Base64编码的图片大小。
     *
     * @param base64Image Base64编码的图片字符串。
     * @return 图片的大小，单位：字节。
     */
    public static int calculateBase64EncodedImageSize(String base64Image) {
        // Base64编码的字符串，每4个字符代表3个字节。
        // 因此，原始大小可以通过总长度乘以3/4得到，需要考虑等号(`=`)的填充。

        String image = base64Image.substring(22); // 需要计算文件流大小，首先把头部的data:image/png;base64,（注意有逗号）去掉。

        // 去掉等号
        int endIndex = image.indexOf("=");
        if (endIndex != -1) {
            image = image.substring(0, endIndex);
        }

        // Base64编码的字符串长度与原始字节长度的关系
        int strLength = image.length();
        int size = (strLength * 3) / 4;
        return size;
    }
}